package com.example.websocket.excel.util;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class FileUtils {
	/**
	 * 同步两个文件夹下最新文件，取文件修改时间
	 * @param file1
	 * @param file2
	 */
	public static void syncFile(File file1, File file2) {
		if(file1.isFile()) { 
			if(file2.isDirectory())
				return;
			long modified1 = file1.lastModified();
			long modified2 = file2.lastModified();
			if(modified1 != modified2) {
				File newFile = modified1 > modified2 ? file1 : file2;
				File oldFile = modified1 < modified2 ? file1 : file2;
				clear(oldFile);
				copy(newFile, oldFile);
				oldFile.setLastModified(newFile.lastModified());
			}
		}else if(file1.isDirectory()){
			if(file2.isFile())
				return;
			if(!file2.exists())
				file2.mkdirs();
			File[] child = file1.listFiles();
			Set<String> nameSet = new HashSet<>();
			for (File file : child) {
				File f = new File(file2.getAbsolutePath() + File.separator + file.getName());
				if(file.isDirectory()) {
					if(!f.exists())
						f.mkdirs();
					syncFile(file, f);
				}else {
					nameSet.add(file.getName());
					syncFile(file, f);
				}
			}
			File[] otherFiles = file2.listFiles(new FilenameFilter() {
				@Override
				public boolean accept(File dir, String name) {
					return !(nameSet.contains(name));
				}
			});
			for (File file : otherFiles) {
				File f = new File(file1.getAbsolutePath() + File.separator + file.getName());
				if(file.isDirectory()) {
					if(!f.exists())
						f.mkdirs();
					syncFile(file, f);
				}else {
					nameSet.add(file.getName());
					syncFile(file, f);
				}
			}
		}
	}
	/**
	 * 清空文件所有内容
	 * @param file
	 */
	public static void clear(File file) {
		if(file != null && file.exists() && file.isFile()) {
			try {
				OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file));
				outputStream.write(new byte[0]);
				outputStream.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	/**
	 * 获取class文件在服务器中的路径
	 * @return
	 */
	public static String getClassFile(){
		String url = null;
		try {
			File f = new File(URLDecoder.decode(FileUtils.class.getResource("/log4j.properties").getFile(), "utf-8"));
			if(!f.exists()){
				f = new File(URLDecoder.decode(FileUtils.class.getResource("../../../log4j.properties").getFile(), "utf-8"));
			}
			url = URLDecoder.decode(f.getParent(), "utf-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return url;
	}
	/**
	 * 将文件复制到指定目录
	 * @param file 复制的文件
	 * @param newFile 得到的新文件
	 * @author 高建涛 2010-6-21上午09:09:26
	 */
	public static void copy(File file, File newFile){
		try {
			if (file == null || !file.exists() || newFile == null)
				return;
			File dir = newFile.getParentFile();
			if (!dir.exists()) dir.mkdirs();
			InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
			OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(newFile));
			copy(inputStream, outputStream);
			outputStream.close();
			inputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 將读入流数据读取到写入流
	 * @param inputStream 读入流
	 * @param outputStream 写入流
	 * @throws IOException
	 * @author 高建涛 2010-6-21上午10:42:29
	 */
	public static void copy(InputStream inputStream, OutputStream outputStream) throws IOException{
		byte[] b = new byte[1024];
		int len;
		while((len = inputStream.read(b)) != -1){
			outputStream.write(b, 0, len);
		}
	}
	/**
	 * 格式化文件路径，去除“\/”等不规范的文件路径
	 * @param file
	 * @return
	 */
	public static String format(String file){
		if(file == null)
			return null;
		String rfile = file.replaceAll("\\\\", "/").replaceAll("/{2,}", "/");
		return rfile;
	}
	/**
	 * 删除文件或者目录，包括目录下的子目录
	 * @param file
	 */
	public static void delete(File file){
		if(file.isDirectory()){
			File[] fs = file.listFiles();
			for (int i = 0; i < fs.length; i++) {
				delete(fs[i]);
			}
		}
		file.delete();
	}
	
	/**
	 * 完整文件名，包括后缀名，不包含目录路径
	 */
	public final static int FULLNAME = 1;
	/**
	 * 完整文件名，不包括后缀名，不包含目录路径
	 */
	public final static int SINGLENAME = 2;
	/**
	 * 后缀名
	 */
	public final static int FIX = 3;
	/**
	 * 目录路径
	 */
	public final static int PATH = 4;
	
	/**
	 * 获取指定文件路径对应的文件名，如果不存在，则返回“”
	 * @param fileName 指定文件名
	 * @param type FileUtils.FULLNAME、FileUtils.SINGLENAME、FileUtils.FIX、FileUtils.PATH
	 * @return 文件名
	 */
	public static String findName(String file, int type){
		if(file == null)
			return "";
		String[] reg = {
				".*[\\\\/]",
				"[^\\\\/|*<>:\"?]+",
				"[^\\\\/|*<>:\"?\\.]+"
		};
		boolean hasPath = file.indexOf("/") != -1 || file.indexOf("\\") != -1;
		boolean hasFix = file.indexOf(".") != -1;
		StringBuffer regBuf = new StringBuffer();
		switch(type) {
			case PATH:{
				regBuf.append("(");
				if(hasPath)
					regBuf.append(reg[0]);
				else
					return "";
				regBuf.append(")");
				regBuf.append(reg[1]);
				if(hasFix)
					regBuf.append("\\.").append(reg[2]);
				break;
			}
			case FULLNAME:{
				if(hasPath)
					regBuf.append(reg[0]);
				regBuf.append("(");
				regBuf.append(reg[1]);
				if(hasFix)
					regBuf.append("\\.").append(reg[2]);
				regBuf.append(")");
				break;
			}
			case SINGLENAME:{
				if(hasPath)
					regBuf.append(reg[0]);
				regBuf.append("(");
				regBuf.append(reg[1]);
				regBuf.append(")");
				if(hasFix)
					regBuf.append("\\.").append(reg[2]);
				break;
			}
			case FIX:{
				if(hasPath)
					regBuf.append(reg[0]);
				regBuf.append(reg[1]);
				if(hasFix)
					regBuf.append("\\.").append("(").append(reg[2]).append(")");
				else
					return "";
				break;
			}
			default:{
				return "";
			}
		}
		Pattern	pattern = Pattern.compile(regBuf.toString());
		Matcher matcher = pattern.matcher(file);
		if(matcher.matches())
			return matcher.group(1);
		else
			return "";
	}
	/**
	 * 增加文件路径目录，并格式化
	 * @param fileName
	 * @param newDir
	 * @return
	 */
	public static String append(String... newDir) {
		return Optional.ofNullable(newDir)
			.map(Arrays::stream)
			.map(s -> s.filter(DataUtils::nonEmpty).collect(Collectors.joining(File.separator)))
			.map(FileUtils::format)
			.orElse(null);
	}
	/**
	 * 获取流的字节长度
	 * @param in 流
	 * @return 字节长度
	 * @throws IOException
	 * @author 高建涛 2010-6-21下午09:16:57
	 */
	public static int length(InputStream in){
		int len = 0;
		try {
			len = in.available();
		} catch (IOException e) {
			try {
				BufferedInputStream bis=new BufferedInputStream(in);
				int l = 0;
				while((l = bis.read())!= -1){
					l ++;
				}
				len = l;
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
		return len;
	}
	
	/**
	 * 读取网络文件
	 * @param path
	 * @return
	 */
	public static InputStream getURLFileInputStream(String path) {
		URL url = null;
		HttpURLConnection conn = null;
		try {
			url = new URL(path);
			conn = (HttpURLConnection)url.openConnection();
			// 设置超时为3秒
			conn.setConnectTimeout(3000);
			// 防止屏蔽程序抓取而返回403错误
			conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
			// 得到输入流
			return conn.getInputStream();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 获取url斜杆后的内容
	 * @param url
	 * @param position
	 * @return
	 */
	public static String getURLFileName(String url, int position) {
		String fileName = null;
		try {
			URL r = new URL(url);
			url = r.getFile();
			String pattern = "[^/]+(?=/)";
			Pattern p = Pattern.compile(pattern);
			Matcher m = p.matcher(url);
			if (m.find()) {
				fileName = m.group(position);
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
		return fileName;
	}
	
	/**
	 * 
	 * @param ins
	 * @param file
	 */
	public static void inputStreamToFile(InputStream ins, File file) {
		try {
			OutputStream os = new FileOutputStream(file);
			int bytesRead = 0;
			byte[] buffer = new byte[8192];
			while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
				os.write(buffer, 0, bytesRead);
			}
			os.close();
			ins.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void deleteTempFile(File file) {
		if (file != null) {
			File delFile = new File(file.toURI());
			delFile.delete();
		}
	}

}
